//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES.
//
//===----------------------------------------------------------------------===//

#ifndef LIBCUDACXX_TEST_BITSET_TEST_CASES_H
#define LIBCUDACXX_TEST_BITSET_TEST_CASES_H

#include <cuda/std/array>
#include <cuda/std/bitset>
#include <cuda/std/tuple>

#include "template_cost_testing.h" // for base cases of REPEAT_*
#include "test_macros.h"

#define BITSET_TEST_CONSTEXPR constexpr

#define NUMARGS(...) (::cuda::std::tuple_size<decltype(::cuda::std::make_tuple(__VA_ARGS__))>::value)
#define DEFINE_CASES(N, ...)                                                                                    \
  __host__ __device__ BITSET_TEST_CONSTEXPR cuda::std::array<const char*, NUMARGS(__VA_ARGS__)> get_test_cases( \
    cuda::std::integral_constant<int, N>)                                                                       \
  {                                                                                                             \
    return {{__VA_ARGS__}};                                                                                     \
  }

DEFINE_CASES(0, "")

DEFINE_CASES(1, "0", "1")

DEFINE_CASES(2, "00", "01", "10", "11")

DEFINE_CASES(
  31,
  "0000000000000000000000000000000",
  "0000000000000000000000000000001",
  "1000000000000000000000000000000",
  "1000000000000000000000000000001",
  "1000000000000000000001000000001",
  "0000000000000000111111111111111",
  "1000000000000000111111111111111",
  "1111111111111111000000000000000",
  "1111111111111111000000000000001",
  "1010101010101010101010101010101",
  "0101010101010101010101010101010",
  "1111111111111111111111111111111")

DEFINE_CASES(
  32,
  "00000000000000000000000000000000",
  "00000000000000000000000000000001",
  "10000000000000000000000000000000",
  "10000000000000000000000000000001",
  "10000000000000000000111000000001",
  "00000000000000001111111111111111",
  "10000000000000001111111111111111",
  "11111111111111110000000000000000",
  "11111111111111110000000000000001",
  "10101010101010101010101010101010",
  "01010101010101010101010101010101",
  "11111111111111111111111111111111")

DEFINE_CASES(
  33,
  "000000000000000000000000000000000",
  "000000000000000000000000000000001",
  "100000000000000000000000000000000",
  "100000000000000000000000000000001",
  "100000000000000000001110000000001",
  "000000000000000011111111111111111",
  "100000000000000011111111111111111",
  "111111111111111100000000000000000",
  "111111111111111100000000000000001",
  "101010101010101010101010101010101",
  "010101010101010101010101010101010",
  "111111111111111111111111111111111")

DEFINE_CASES(
  63,
  "000000000000000000000000000000000000000000000000000000000000000",
  "000000000000000000000000000000000000000000000000000000000000001",
  "100000000000000000000000000000000000000000000000000000000000000",
  "100000000000000000000000000000000000000000000000000000000000001",
  "100000000000000000000000001111100000000000000000000000000000001",
  "000000000000000000000000000000001111111111111111111111111111111",
  "100000000000000000000000000000001111111111111111111111111111111",
  "111111111111111111111111111111110000000000000000000000000000000",
  "111111111111111111111111111111110000000000000000000000000000001",
  "101010101010101010101010101010101010101010101010101010101010101",
  "010101010101010101010101010101010101010101010101010101010101010",
  "111111111111111111111111111111111111111111111111111111111111111")

DEFINE_CASES(
  64,
  "0000000000000000000000000000000000000000000000000000000000000000",
  "0000000000000000000000000000000000000000000000000000000000000001",
  "1000000000000000000000000000000000000000000000000000000000000000",
  "1000000000000000000000000000000000000000000000000000000000000001",
  "1000000000000000000000000011111000000000000000000000000000000001",
  "0000000000000000000000000000000011111111111111111111111111111111",
  "1000000000000000000000000000000011111111111111111111111111111111",
  "1111111111111111111111111111111100000000000000000000000000000000",
  "1111111111111111111111111111111100000000000000000000000000000001",
  "1010101010101010101010101010101010101010101010101010101010101010",
  "0101010101010101010101010101010101010101010101010101010101010101",
  "1111111111111111111111111111111111111111111111111111111111111111")

DEFINE_CASES(
  65,
  "00000000000000000000000000000000000000000000000000000000000000000",
  "00000000000000000000000000000000000000000000000000000000000000001",
  "10000000000000000000000000000000000000000000000000000000000000000",
  "10000000000000000000000000000000000000000000000000000000000000001",
  "10000000000000000000000000011111000000000000000000000000000000001",
  "00000000000000000000000000000000011111111111111111111111111111111",
  "10000000000000000000000000000000011111111111111111111111111111111",
  "11111111111111111111111111111111000000000000000000000000000000000",
  "11111111111111111111111111111111000000000000000000000000000000001",
  "10101010101010101010101010101010101010101010101010101010101010101",
  "01010101010101010101010101010101010101010101010101010101010101010",
  "11111111111111111111111111111111111111111111111111111111111111111")

#define BITSET_ZERO()    "0"
#define BITSET_ONE()     "1"
#define BITSET_ONEZERO() "10"
#define BITSET_ZEROONE() "10"

#define REPEAT_8(DO_IT) DO_IT() DO_IT() DO_IT() DO_IT() DO_IT() DO_IT() DO_IT() DO_IT()
#define REPEAT_9(DO_IT) REPEAT_8(DO_IT) DO_IT()
#define REPEAT_90(DO_IT) \
  REPEAT_10(DO_IT)       \
  REPEAT_10(DO_IT)       \
  REPEAT_10(DO_IT) REPEAT_10(DO_IT) REPEAT_10(DO_IT) REPEAT_10(DO_IT) REPEAT_10(DO_IT) REPEAT_10(DO_IT) REPEAT_10(DO_IT)
#define REPEAT_99(DO_IT)  REPEAT_90(DO_IT) REPEAT_9(DO_IT)
#define REPEAT_400(DO_IT) REPEAT_100(DO_IT) REPEAT_100(DO_IT) REPEAT_100(DO_IT) REPEAT_100(DO_IT)
#define REPEAT_499(DO_IT) REPEAT_400(DO_IT) REPEAT_99(DO_IT)
#define REPEAT_900(DO_IT) REPEAT_500(DO_IT) REPEAT_400(DO_IT)
#define REPEAT_998(DO_IT) REPEAT_900(DO_IT) REPEAT_90(DO_IT) REPEAT_8(DO_IT)
#define REPEAT_999(DO_IT) REPEAT_900(DO_IT) REPEAT_99(DO_IT)

DEFINE_CASES(
  1000,
  REPEAT_1000(BITSET_ZERO),
  REPEAT_999(BITSET_ZERO) BITSET_ONE(),
  BITSET_ONE() REPEAT_999(BITSET_ZERO),
  BITSET_ONE() REPEAT_998(BITSET_ZERO) BITSET_ONE(),
  BITSET_ONE() REPEAT_400(BITSET_ZERO) REPEAT_99(BITSET_ONE) REPEAT_499(BITSET_ZERO) BITSET_ONE(),
  REPEAT_500(BITSET_ZERO) REPEAT_500(BITSET_ONE),
  BITSET_ONE() REPEAT_499(BITSET_ZERO) REPEAT_500(BITSET_ONE),
  REPEAT_500(BITSET_ONE) REPEAT_500(BITSET_ZERO),
  REPEAT_500(BITSET_ONE) REPEAT_499(BITSET_ZERO) BITSET_ONE(),
  REPEAT_500(BITSET_ONEZERO),
  REPEAT_500(BITSET_ZEROONE),
  REPEAT_1000(BITSET_ONE))

#endif // !LIBCUDACXX_TEST_BITSET_TEST_CASES_H
